/***************************************************************************
 *   Copyright (C) 2009 by umbacos@gmail.com                               *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "udm-common.h"

char* dcgi;
char* droo;
char* dbin;
char* wget;
char* ctor;
char* dwww;
char* dufb;
char* ddnl;
char* dtrk;
char* fcnf;
char* argv0;
char* filter;
char* pidfile;

void get_post_cookie();
void get_directories ( char * file );
void * xmalloc ( size_t size );
int filter_select ( struct dirent *entry );
void send_message ( char * msg, char * inf );

char * file_from_inode (char * inode) {

	long ino;
	struct dirent **namelist;
	struct stat buf;
	int n;
	char * ndnl = xmalloc ( 1000 );

	ino = atol(inode);
	memset ( ndnl, 0, 1000 );
	strcpy ( ndnl, ddnl );

	if ( getenv ( "FORM_curdir" ) )
		strncat ( ndnl, getenv ( "FORM_curdir" ), 1000 - strlen ( ddnl ) );
	chdir ( ndnl );

	filter = "";
	n = scandir ( ndnl, &namelist, ( void * ) filter_select, NULL );

	if ( n < 0 )
		send_message ( "Can't scan download directory", ndnl );
	else {
		while ( n-- ) {
			stat ( namelist[n]->d_name, &buf );
			if ( buf.st_ino == ino) {
				memset ( ndnl, 0, 1000 );
				strcat ( strcpy ( ndnl, "/" ), namelist[n]->d_name );
				return strdup(ndnl);
			}
		}
		send_message ( "What inode did you send?", "" );
	}
}

/* Send a file to the client */
void do_download ( char *ino ) {

	struct stat statbuf;
	char * download_file;
	char   ndnl[1000];
	char * fil;
	int    n_bytes;
	int    w_bytes;
	int    buf[1024];
	FILE*  df;

#ifdef DEBUG
	mylog ( "do_download START: ", ino );
#endif
	memset ( &ndnl, 0, 1000 );

	fil = file_from_inode ( ino );

#ifdef DEBUG
	mylog ( "file_from_inode:", fil );
	mylog ( "FORM_curdir:", getenv ( "FORM_curdir" ) );
#endif

	if ( strlen ( fil ) > 0 )
		strcat ( strcat ( strcpy ( ndnl, ddnl ), getenv ( "FORM_curdir" ) ), fil );
	else
		send_message ( "Unspecified file", NULL );
#ifdef DEBUG
	mylog ( "do_download ndnl:", ndnl );
#endif
	if ( strstr ( ndnl, "/.." ) != NULL )
		send_message ( "Filename error (contains /..)", ndnl );

	if ( stat ( ndnl, &statbuf ) < 0 )
		send_message ( "File not found:", fil );

	if ( ( df = fopen ( ndnl, "rb" ) ) == NULL )
		send_message ( "Unable to access download file:", fil );

	printf ( "Content-type: application/octet-stream\n" );
	printf ( "Pragma: no-cache\n" );
	printf ( "Expires: 0\n" );
	printf ( "Content-disposition: filename=\"%s\"\n", rindex ( ndnl, '/' ) + 1 );
	printf ( "Content-length: %Ld\n\n", ( long long ) statbuf.st_size );

#ifdef DEBUG
	char s[200];
	long tot = 0;
	long tow = 0;
	mylog ( "done headers, start dumping of ", ndnl );
#endif
	while ( ( n_bytes = fread ( buf, 1, sizeof ( buf ), df ) ) > 0 ) {
#ifdef DEBUG
		tot += n_bytes;
		sprintf(s, "%ld bytes - sizeof buf=%d", tot, sizeof ( buf ));
		mylog ( "read ", s );
#endif

		if ( ( w_bytes = fwrite ( buf, n_bytes, 1, stdout ) ) != 1 )
			send_message ( "Fatal error in downloading ", fil );
#ifdef DEBUG
		tow += w_bytes;
#endif
	}
	fclose ( df );

#ifdef DEBUG
	mylog ( "done dumping of ", ndnl );
	memset ( s, 0, 20 );
	sprintf ( s, "%lld", statbuf.st_size );
	mylog ( "originally:", s );
	memset ( s, 0, 20 );
	sprintf ( s, "%ld", tot );
	mylog ( "fread from:", s );
	memset ( s, 0, 20 );
	sprintf ( s, "%ld", tow );
	mylog ( "downloaded:", s );
#endif
	exit ( 0 );
}

int main ( int argc, char** argv ) {

	char fil[501];
	memset ( &fil, 0, 500 );

	get_directories ( strdup ( argv[0] ) );
	get_post_cookie ();

	if ( getenv ( "FORM_file" ) )
		strncpy ( fil, getenv ( "FORM_file" ), 500 );
	else
		send_message ( "ERROR: no inode provided", "" );
#ifdef DEBUG
	mylog ( "fil:", fil );
#endif

	do_download ( fil );
	return 0;
}
